<?php
/**
 *  顺丰企业服务平台api
 *  加于20180326
 */

namespace app\common\tool;

use think\Db;

class BSP
{
    protected static $config = [
/*        'server' => 'http://bspoisp.sit.sf-express.com:11080/bsp-oisp/sfexpressService',
        'checkword' => '869eQvoZDmMLnjtT',
        'accesscode' => 'HZBXKJ',*/
        'server' => 'http://bsp-oisp.sf-express.com/bsp-oisp/sfexpressService',
        'checkword' => 'Tl7dIpAgVEGlyJOKfOCJQ3Eb1rchTiAD',
        'accesscode' => '5717085362',
    ];

    protected static $ret = [
        'head' => 'ERR',
        'message' => '系统错误',
        'code' => -1
    ];

    /**
     * 下单
     */
    public static function Order($orderId, $senderInfo, $data, $cargoes = [], $addedServices = [])
    {
        $order = '<Order ';
        foreach ($data as $k => $v) {
            $order .= $k . '=' . '"' . $v . '" ';
        }
        if (count($cargoes) > 0 || count($addedServices) > 0) {
            $order = trim($order) . '>';
            if (is_array($cargoes) && count($cargoes) > 0) {
                $order .= self::Cargo($cargoes);
            }
            if (is_array($addedServices) && count($addedServices) > 0) {
                $order .= self::AddedService($addedServices);
            }
            $order .= '</Order>';
        } else {
            $order .= ' />';
        }
        $xml = self::buildXml($order, 'OrderService');
        $verifyCode = self::sign($xml, self::$config['checkword']);
        $params = ['xml' => $xml, 'verifyCode' => $verifyCode];
        $params = http_build_query($params, '', '&');
        $res = self::curlRequest(self::$config['server'], $params);
        $res = self::getResponse($res, 'OrderResponse');
        if (isset($res['head']) && $res['head'] == 'OK') {
            Db::name('zj_express_order')->insert([
                'book_order_id' => $orderId,
                'express_order_id' => $res['orderid'],
                'express_no' => $res['mailno'],
                'filter_result' => $res['filter_result'],
                'send_start_time' => strtotime($data['sendstarttime']),
                'sender_info' => json_encode($senderInfo),
                'remark' => $data['remark'],
                'create_time' => time()
            ]);
            return true;
        } elseif (isset($res['head']) && $res['head'] == 'ERR') {
            return $res['message'];
        }
        return false;
    }

    /**
     * 订单确认/取消
     */
    public static function orderConfirm()
    {
        $data = [
            'orderid' => 'BSP20180126135616785322',
            'dealtype' => 2,
        ];
        $order = '<OrderConfirm ';
        foreach ($data as $k => $v) {
            $order .= $k . '=' . '"' . $v . '" ';
        }
        $order .= ' />';
        $xml = self::buildXml($order, 'OrderConfirmService');
        $verifyCode = self::sign($xml, self::$config['checkword']);
        $params = ['xml' => $xml, 'verifyCode' => $verifyCode];
        $params = http_build_query($params, '', '&');
        $res = self::curlRequest(self::$config['server'], $params);
        return self::getResponse($res, 'OrderResponse');
    }

    /**
     * 订单查询
     */
    public static function orderQuery()
    {
        $data = ['orderid' => 'BSP20180202182918349946'];
        $order = '<OrderSearch ';
        foreach ($data as $k => $v) {
            $order .= $k . '=' . '"' . $v . '" ';
        }
        $order .= ' />';
        $xml = self::buildXml($order, 'OrderSearchService');
        $verifyCode = self::sign($xml, self::$config['checkword']);
        $params = ['xml' => $xml, 'verifyCode' => $verifyCode];
        $params = http_build_query($params, '', '&');
        $res = self::curlRequest(self::$config['server'], $params);
        return self::getResponse($res, 'OrderResponse');
    }

    /**
     * 物流查询
     */
    public static function orderRoute($expressNo)
    {
        $data = [
            'tracking_type' => '1',
            'tracking_number' => $expressNo,
            'method_type' => '1'
        ];
        $order = '<RouteRequest ';
        foreach ($data as $k => $v) {
            $order .= $k . '=' . '"' . $v . '" ';
        }
        $order .= ' />';
        $xml = self::buildXml($order, 'RouteService');
        $verifyCode = self::sign($xml, self::$config['checkword']);
        $params = ['xml' => $xml, 'verifyCode' => $verifyCode];
        $params = http_build_query($params, '', '&');
        $res = self::curlRequest(self::$config['server'], $params);
        $arr = self::xmlToArray($res);
        unset($res);
        if (empty($arr) || $arr['Head'] != 'OK' || empty($arr['Body']['RouteResponse']['Route'])) {
            // return '暂无物流信息，请稍后再试';
            $result_data = array('status' => 0, 'msg' => "无物流信息，请联系商家！");
            return $result_data;
        }
        $data = [];
        if(count($arr['Body']['RouteResponse']['Route'])==1) {//修改于20180327
            $data[] = ['context' => $arr['Body']['RouteResponse']['Route']['@attributes']['remark'] , 'time' => $arr['Body']['RouteResponse']['Route']['@attributes']['accept_time']];
        }else {
            foreach ($arr['Body']['RouteResponse']['Route'] as $item) {
                $data[] = ['context' => $item['@attributes']['remark'] , 'time' => $item['@attributes']['accept_time']];
            }
        }
        // print_r($data);exit;
        $data['status'] = 1;
        return array_reverse($data);
    }

    private static function Cargo($cargoes)
    {
        $data = '';
        if (count($cargoes) > 0) {
            foreach ($cargoes as $item) {
                if (count($item) > 0) {
                    $root = '<Cargo ';
                    foreach ($item as $k => $v) {
                        $root .= $k . '="' . $v . '" ';
                    }
                    $root .= '></Cargo>';
                    $data .= $root;
                }
            }
        }
        return $data;
    }

    private static function AddedService($AddedServices)
    {
        $data = '';
        if (count($AddedServices) > 0) {
            foreach ($AddedServices as $item) {
                if (count($item) > 0) {
                    $root = '<AddedService ';
                    foreach ($item as $k => $v) {
                        $root .= $k . '="' . $v . '" ';
                    }
                    $root .= '></AddedService>';
                    $data .= $root;
                }
            }
        }
        return $data;
    }

    private static function buildXml($bodyData, $serviceName)
    {
        $xml = '<Request service="' . $serviceName . '" lang="zh-CN">' .
            '<Head>' . self::$config['accesscode'] . '</Head>' .
            '<Body>' . $bodyData . '</Body>' .
            '</Request>';
        return $xml;
    }

    private static function sign($data, $checkword)
    {
        $string = trim($data) . trim($checkword);
        $md5 = md5(mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string)), true);
        $sign = base64_encode($md5);
        return $sign;
    }

    private static function getResponse($data, $name)
    {
        $ret = self::$ret;
        $xml = @simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
        if ($xml) {
            $ret = [];
            $ret['head'] = (string)$xml->Head;
            if ($xml->Head == 'OK') {
                $ret = array_merge($ret, self::getData($xml, $name));
            }
            if ($xml->Head == 'ERR') {
                $ret = array_merge($ret, self::getErrorMessage($xml));
            }
        }
        return $ret;
    }

    private static function getErrorMessage($xml)
    {
        $ret = [];
        $ret['message'] = (string)$xml->ERROR;
        if (isset($xml->ERROR[0])) {
            foreach ($xml->ERROR[0]->attributes() as $key => $val) {
                $ret[$key] = (string)$val;
            }
        }
        return $ret;
    }

    private static function getData($xml, $name)
    {
        $ret = [];
        if (isset($xml->Body->$name)) {
            foreach ($xml->Body->$name as $v) {
                foreach ($v->attributes() as $key => $val) {
                    $ret[$key] = (string)$val;
                }
            }
        }
        return $ret;
    }

    private static function xmlToArray($xml)
    {
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    private static function curlRequest($url, $data = '')
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置头文件的信息作为数据流输出
        curl_setopt($curl, CURLOPT_HEADER, 0);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        if (false !== strpos($url, 'https://')) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        }
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }
}
